﻿using System;
using System.Collections.Generic;
using System.Data;
using UDS.Components;
using System.Diagnostics;

namespace UDS.Entity
{
    public enum FlowJumpComparisonMode
    {
        [DisplayName(">", "大于")]
        GreaterThan = 1,

        [DisplayName("=", "等于")]
        Equal = 2,

        [DisplayName("<", "小于")]
        LessThan = 3,

        [DisplayName(">=", "大于等于")]
        GreaterThanOrEqual = 4,

        [DisplayName("<=", "小于等于")]
        LessThanOrEqual = 5,

        [DisplayName("<>", "不等")]
        NotEqual = 6,
    }

    [Serializable]
    public class FlowJump
    {
        #region properties

        public string FieldName
        {
            get;
            set;
        }

        /// <summary>
        /// Get the description for <see cref="FieldName"/>.
        /// </summary>
        public string FieldDescription
        {
            get;
            private set;
        }

        public FlowJumpComparisonMode ComparisonMode
        {
            get;
            set;
        }

        public double CompareValue
        {
            get;
            set;
        }

        public int FlowID
        {
            get;
            set;
        }

        public int StepID
        {
            get;
            set;
        }

        /// <summary>
        /// Get the name of the step.
        /// </summary>
        public string StepToName
        {
            get;
            private set;
        }

        public int Priority
        {
            get;
            set;
        }

        public int StepTo
        {
            get;
            set;
        }

        public FlowRule FlowRule
        {
            get;
            set;
        }

        #endregion

        /// <summary>
        /// Add a new jump.
        /// </summary>
        /// <param name="FlowID"></param>
        /// <param name="StepID"></param>
        /// <param name="FieldName"></param>
        /// <param name="comparisonMode"></param>
        /// <param name="CompareValue"></param>
        /// <param name="ToFlowID">The id of the targeting flow, or zero for the current flow.</param>
        /// <param name="ToStepID"></param>
        /// <param name="FlowRule"></param>
        /// <returns></returns>
        public static int AddJump(int FlowID, int StepID, string FieldName, FlowJumpComparisonMode comparisonMode, double CompareValue, int ToFlowID, int ToStepID, FlowRule FlowRule)
        {
            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, FlowID),
                Database.MakeInParam("@StepID", SqlDbType.Int, 4, StepID),
                Database.MakeInParam("@FieldName", SqlDbType.NVarChar, 50, FieldName),
                Database.MakeInParam("@Compare", SqlDbType.NVarChar, 50, Utility.GetEnumDisplayName(comparisonMode)),
                Database.MakeInParam("@CompareValue", SqlDbType.Float, 8, CompareValue),
                Database.MakeInParam("@ToFlowID", SqlDbType.Int, 4, ToFlowID),
                Database.MakeInParam("@ToStepID", SqlDbType.Int, 4, ToStepID),
                Database.MakeInParam("@FlowRule", SqlDbType.Int, 4, (int)FlowRule)
            };

            using (var db = new Database())
            {
                return db.RunProc("dbo.sproc_Flow_AddJump_V3", parameters);
            }
        }

        /// <summary>
        /// Delete the jump.
        /// </summary>
        public static int DeleteJump(int FlowID, int StepID, int Priority)
        {
            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, FlowID),
                Database.MakeInParam("@StepID", SqlDbType.Int, 4, StepID),
                Database.MakeInParam("@Priority", SqlDbType.Int, 4, Priority)
            };

            using (var db = new Database())
            {
                return db.RunProc("dbo.sproc_Flow_DeleteJump_V2", parameters);
            }
        }

        /// <summary>
        /// Move up the jump.
        /// </summary>
        public static int MoveUpJump(int FlowID, int StepID, int Priority)
        {
            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, FlowID),
                Database.MakeInParam("@StepID", SqlDbType.Int, 4, StepID),
                Database.MakeInParam("@Priority", SqlDbType.Int, 4, Priority)
            };

            using (var db = new Database())
            {
                return db.RunProc("dbo.sproc_Flow_MoveUpJump_V2", parameters);
            }
        }

        /// <summary>
        /// Get all the jumps defined for the specified step.
        /// </summary>
        public static IList<FlowJump> GetJumps(int flowId, int stepId)
        {
            var parameters = new[]
            {
                Database.MakeInParam("@FlowID", SqlDbType.Int, 4, flowId),
                Database.MakeInParam("@StepID", SqlDbType.Int, 4, stepId),
            };
            var mySQL = new Database();
            var list = new List<FlowJump>();
            using (var dr = mySQL.RunDataReader("dbo.sproc_Flow_GetJump_V3", parameters))
            {
                while (dr.Read())
                {
                    list.Add(ReadFlowJump(dr));
                }
            }
            return list;
        }

        #region help methods
        private static FlowJump ReadFlowJump(IDataReader dr)
        {
            FlowJump j = new FlowJump();
            j.FieldName = Convert.ToString(dr["FieldName"]);
            j.FieldDescription = (string.Compare(j.FieldName, FlowStyleDescription.Caste, true) == 0) ? "《职级》" : Convert.ToString(dr["Field_Description"]);
            j.ComparisonMode = ReadComparisonMode(Convert.ToString(dr["Compare"]));
            j.CompareValue = Convert.ToDouble(dr["CompareValue"]);
            j.FlowID = (int)dr["Flow_ID"];
            j.StepID = (int)dr["Step_ID"];
            j.Priority = Utility.ReadInt32(dr["Priority"], 0);
            j.StepTo = Utility.ReadInt32(dr["To_Step_ID"], 0);
            j.StepToName = Convert.ToString(dr["StepTo_Name"]);
            j.FlowRule = (FlowRule)Utility.ReadInt32(dr["Flow_Rule"], (int)FlowRule.Staff);

            return j;
        }

        private static IDictionary<int, DisplayNameAttribute> s_nameMap;
        private static FlowJumpComparisonMode ReadComparisonMode(string s)
        {
            if (s_nameMap == null)
            {
                s_nameMap = Utility.GetEnumDisplayNames(typeof(FlowJumpComparisonMode));
            }
            Debug.Assert(s_nameMap != null);
            Debug.Assert(s_nameMap.Count > 0);

            if (!string.IsNullOrEmpty(s))
            {
                s = s.Trim();
                foreach (var kvp in s_nameMap)
                {
                    if (string.Compare(s, kvp.Value.Name) == 0)
                    {
                        return (FlowJumpComparisonMode)kvp.Key;
                    }
                }
            }

            // Not found.
            // We will use the default value to avoid breaking the builds.
            return FlowJumpComparisonMode.GreaterThan;
        }
        #endregion
    }
}
